package org.tabcap.workspace.manager;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.LinkedList;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.tabcap.TCInstance;
import org.tabcap.workspace.TCWorkspace;
import org.tabcap.workspace.document.BaseDocument;

public abstract class BaseWorkspaceManager implements TCWorkspaceManager
{
	protected TCInstance instance;
	protected String currentDirectory;
	protected LinkedList<TCWorkspace> workspaces;
	protected TCWorkspace activeWorkspace;
	protected JTabbedPane tabs;
	
	public BaseWorkspaceManager(TCInstance instance)
	{
		this.instance = instance;
		workspaces = new LinkedList<TCWorkspace>();
		tabs = new JTabbedPane();
		tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
		tabs.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				activeWorkspace = workspaceAt(tabs.getSelectedIndex());
			} } );
	}

	@Override public JComponent view() { return tabs; }
	@Override public TCWorkspace current() { return activeWorkspace; }
	
	public TCWorkspace workspaceAt(int index)
	{
		if(index >= 0)
			for(TCWorkspace doc : workspaces)
				if(doc == tabs.getComponentAt(index))
					return doc;
		return null;
	}
	
	public boolean fileIsOpen(File file)
	{
		return fileIsOpen(file.getAbsolutePath());
	}
	
	public boolean fileIsOpen(String filepath)
	{
		for(TCWorkspace workspace : workspaces)
			if(workspace.document().file().getAbsolutePath().equals(filepath))
				return true;
		return false;
	}
	
	public int indexOfWorkspace(TCWorkspace workspace)
	{
		for(int i = 0; i < tabs.getTabCount(); i++)
			if(workspace == tabs.getComponentAt(i))
				return i;
		return -1;
	}
	
	public void selectWorkspace(TCWorkspace workspace)
	{
		if(workspace != null)
		{
			int index = indexOfWorkspace(workspace);
			if(index != -1)
				tabs.setSelectedIndex(index);
			activeWorkspace = workspace;
		}
	}
	
	public void selectWorkspace(String filepath)
	{
		if(filepath != null)
			for(TCWorkspace workspace : workspaces)
				if(workspace.document().file().getAbsolutePath().equals(filepath))
				{
					selectWorkspace(workspace);
					return;
				}
	}
	
	protected void addWorkspace(TCWorkspace workspace)
	{
		if(workspace != null && !workspaces.contains(workspace))
		{
			workspaces.add(workspace);
			tabs.addTab(workspace.document().name(), workspace);
			
			JPanel panel = new JPanel(new BorderLayout());
			panel.setOpaque(false);
			panel.add(workspace.label(), BorderLayout.CENTER);
			panel.add(new TabCloseOption(workspace), BorderLayout.EAST);
			int index = tabs.getTabCount() - 1;
			tabs.setTabComponentAt(index, panel);
			tabs.setSelectedIndex(index);
		}
	}
	
	protected void removeWorkspace(TCWorkspace workspace)
	{
		if(workspace != null && workspaces.contains(workspace))
		{
			workspaces.remove(workspace);
			tabs.remove(workspace);
		}
	}
	
	protected void saveWorkspaceAs(TCWorkspace workspace)
	{
		if(workspace != null)
		{
			JFileChooser chooser = new JFileChooser(workspace.document().validFile() ?
					workspace.document().directory() : currentDirectory);
			if(chooser.showSaveDialog(instance.frame()) == JFileChooser.APPROVE_OPTION)
			{
				workspace.document().saveAs(chooser.getSelectedFile());
				currentDirectory = chooser.getCurrentDirectory().getAbsolutePath();
			}
		}
	}
	
	protected void saveWorkspace(TCWorkspace workspace)
	{
		if(workspace != null && workspace.document().needsSave())
			if(workspace.document().validFile())
				workspace.document().save();
			else
				saveWorkspaceAs(workspace);
	}
	
	protected void closeWorkspace(TCWorkspace workspace)
	{
		if(workspace != null)
			if(!workspace.document().isWorthless() && workspace.document().needsSave())
			{
				int n = showUnsavedDialog();
				if(n == 0)
					saveWorkspace(workspace);
				if(n != 2 && n != JOptionPane.CLOSED_OPTION)
					removeWorkspace(workspace);
			}
			else
				removeWorkspace(workspace);
	}
	
	protected int showUnsavedDialog()
	{
		Object[] options = { "Save", "Discard", "Cancel" };
		return JOptionPane.showOptionDialog(instance.frame(),
				    "Document has unsaved changes, do you want to save?",
				    "Warning - Unsaved Changes!",
				    JOptionPane.YES_NO_CANCEL_OPTION,
				    JOptionPane.WARNING_MESSAGE,
				    null, options, options[0]);
	}
	
	protected JButton tabCloseButton(BaseDocument workspace)
	{
		JButton button = new JButton();
		return button;
	}
	
	protected class TabCloseOption extends JPanel
	{
		private static final long serialVersionUID = 5750976942479282313L;
		
		protected TCWorkspace workspace;
		
		public TabCloseOption(TCWorkspace workspace)
		{
			super(new BorderLayout());
			setOpaque(false);
			this.workspace = workspace;
			
			JButton button = new JButton(instance.images().getIcon("Close Tab"));
			button.addActionListener(new TabCloseAction());
			button.setPreferredSize(new Dimension(22, 21));
	        button.setOpaque(false);

			add(button, BorderLayout.EAST);
			this.setBorder(BorderFactory.createEmptyBorder(4, 10, 2, 0));
		}
		
		protected class TabCloseAction implements ActionListener {
			public void actionPerformed(ActionEvent e) {
				closeWorkspace(workspace);
				if(tabs.getTabCount() <= 0)
					openNew();
			} }
	}
}